<?php

namespace App\Models\Tools;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage;
use OSS\Core\OssException;
use OSS\OssClient;

class AliOss
{
    /**
     * 处理初始化OssClient的参数
     * @param string $bucket 存储空间名称
     * @return array
     */
    public static function clientSetting(string $bucket): array
    {
        if (!$bucket) {
            $env = env('APP_ENV') === 'production' ? 'production' : 'testing';
            $bucket = 'lf-' . $env;
        }

        // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
        $accessKeyId = env('OSS_ACCESS_KEY_ID');
        $accessKeySecret = env('OSS_ACCESS_KEY_SECRET');
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        $endpoint = env('OSS_END_POINT');
        $init = [$accessKeyId, $accessKeySecret, $endpoint];

        return [
            'bucket' => $bucket,
            'init' => $init
        ];
    }

    /**
     *  上传文件到oss
     * @param string $object 文件名称
     * @param string $filePath 由本地文件路径加文件名包括后缀，例如/users/local/myFile.txt
     * @param string $bucket 存储空间名称
     * @return bool
     */
    public static function uploadFile(string $object, string $filePath, $bucket = ''): bool
    {
        $setting = self::clientSetting($bucket);
        $bucket = $setting['bucket'];
        try {
            $ossClient = new OssClient(...$setting['init']);
            $ossClient->uploadFile($bucket, $object, $filePath);
            // 删除文件
            Storage::delete($filePath);
        } catch (OssException $e) {
            Log::error(AliOss::class, ['errMsg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            return false;
        }
        return true;
    }

    /**
     * 上传一个已拼接好path的文件到oss（不修改文件名称）
     * @param string $file 已保存的文件path
     * @param string $bucket
     * @return bool
     */
    public static function uploadFileSimplify(string $file, $bucket = ''): bool
    {
        $setting = self::clientSetting($bucket);
        $bucket = $setting['bucket'];
        try {
            $ossClient = new OssClient(...$setting['init']);
            $ossClient->uploadFile($bucket, $file, 'storage/' . $file);
            // 删除这个文件
//            Storage::delete($file);
        } catch (OssException $e) {
            Log::error(AliOss::class, ['errMsg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            return false;
        }
        return true;
    }

    /**
     * 获取图片路径
     * @param string|null $object
     * @param string $bucket
     * @return bool|string
     */
    public static function getUrl($object, $bucket = '')
    {
        if (!$object) return null;
        $signedUrl = Redis::get('ali_oss_' . $object);
        if ($signedUrl) return $signedUrl; // 如果在redis已经存过这个图片，直接返回
        $setting = self::clientSetting($bucket);
        $bucket = $setting['bucket'];
        try {
            $ossClient = new OssClient(...$setting['init']);
            // 生成GetObject的签名URL。
            $signedUrl = $ossClient->signUrl($bucket, $object, 3600);
            // 记录到redis
            Redis::setex('ali_oss_' . $object, 30 * 60, $signedUrl);
            return $signedUrl;
        } catch (OssException $e) {
            Log::error(AliOss::class, ['errMsg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            return null;
        }
    }

    /**
     * 批量获取图片路径
     * @param array $objects
     * @param string $bucket
     * @return bool|array
     */
    public static function getUrls(array $objects, $bucket = '')
    {
        $setting = self::clientSetting($bucket);
        $bucket = $setting['bucket'];
        try {
            $ossClient = new OssClient(...$setting['init']);
            // 生成GetObject的签名URL。
            $signedUrls = [];
            foreach ($objects as $object) {
                $signedUrl = Redis::get('ali_oss_' . $object);
                if ($signedUrl){
                    $signedUrls[] = $signedUrl;
                } else {
                    $signedUrl = $ossClient->signUrl($bucket, $object, 3600);
                    Redis::setex('ali_oss_' . $object, 30 * 60, $signedUrl);
                    $signedUrls[] = $signedUrl;
                }
            }
            return $signedUrls;
        } catch (OssException $e) {
            Log::error(AliOss::class, ['errMsg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            return false;
        }
    }

}
